﻿using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Resources;
using System.Runtime.InteropServices;
using NesEmu.ControlsNet.Properties;
using NesEmu.Core;

namespace NesEmu.ControlsNet
{
    public partial class GameControl : UserControl
    {
        private readonly Bitmap _bitmap;
        private readonly Graphics _graphics;
        private Thread? _gameThread;

        public GameControl()
        {
            InitializeComponent();

            _bitmap = new Bitmap(256, 240, PixelFormat.Format8bppIndexed);

            _graphics = CreateGraphics();
            _graphics.InterpolationMode = InterpolationMode.NearestNeighbor;

            Emulator.DrawFrame += EmulatorOnDrawFrame;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            BackgroundImage = Resources.nesemu;
        }

        private void EmulatorOnDrawFrame(object? sender, DrawFrameEventArgs e)
        {
            var bmpData = _bitmap.LockBits(new Rectangle(0, 0, 256, 240), ImageLockMode.WriteOnly,
                PixelFormat.Format8bppIndexed);

            Marshal.Copy(e.BitmapData, 0, bmpData.Scan0, e.BitmapData.Length);

            _bitmap.UnlockBits(bmpData);
            _graphics.DrawImage(_bitmap, 0, 0, Size.Width, Size.Height);
        }

        public Emulator Emulator { get; } = new();

        public void LoadFromFile(string romFile)
        {
            Emulator.Open(romFile);
        }

        public void Start()
        {
            if (Emulator.Running)
            {
                return;
            }

            UpdateColorPalette(_bitmap, ColorPalettes.Default);
            _gameThread = new Thread(GameThreadProc)
            {
                IsBackground = true
            };
            _gameThread.Start();
        }

        public void SetButtonState(Controller.Buttons button, bool state)
        {
            Emulator.Controller.SetButtonState(button, state);
        }

        public void Stop()
        {
            Emulator.Stop();
            if (_gameThread?.ThreadState == ThreadState.Running) _gameThread.Join();
            BackgroundImage = Resources.nesemu;
        }

        private void UpdateColorPalette(Bitmap bitmap, Color[] colorPalette)
        {
            var palette = bitmap.Palette;
            for (var idx = 0; idx < 64; idx++) palette.Entries[idx] = colorPalette[idx];

            bitmap.Palette = palette;
        }

        private void GameThreadProc()
        {
            // looping in the emulator to execute the instructions.
            Emulator.Run();
        }
    }
}
